import std.stdio;
import tcc.libtcc;
import std.string: toStringz;


void main()
{
	test4();
	writeln("Edit source/app.d to start your project.");
}


enum helloC = `
int main()
{
        //printf("Hello World!");
        return 9;
}
`;

enum helloC2 = `

//#include <tcclib.h>
//__declspec(dllimport) 


typedef struct MyStruct
{

	unsigned char a1;
	unsigned char a2;
	unsigned char a3;
}__attribute__ ((aligned (2))) MyStruct; 



__attribute__((dllimport))
extern char hello[];
int fib(int n)
{
	printf("%s \n", hello);
	printf("%d \n", sizeof(MyStruct));
	if (n <= 1)
			return 1;
	else
			return fib(n-1) + fib(n-2);
}

int main(){
	printf("%d\n", 99);
	return 99;
}
`;

import std.experimental.logger;
//import core.stdc.string;
//import core.stdc.stdlib;

struct MyStruct
{
	//对齐
	align(2):
	int a1;
	int a2;
	int a3;
}
enum mysss = `
typedef struct MyStruct
{

	int a1;
	int a2;
	int a3;
}__attribute__ ((aligned (1))) MyStruct; 
`;

extern(C) 
void disErr(void* opaque, in char* msg)
{
	import core.stdc.stdio:ssprintf = printf;
	ssprintf("ettttt:%s \n", msg);
	//error(msg);
}
void test4()
{
	import tcc.dtinycc;
	string hel = "hello123";
	extern(C) int function(int ) fib1;

	auto mtcc = new cTinyCC();
	mtcc.pfInitScript();

	mtcc.pfCompileString(helloC2);

	mtcc.pfAddSymbol("hello",hel.ptr);

	mtcc.pfRelocate();

	fib1 = mtcc.pfGetSymbol!(typeof(fib1))("fib");
	fib1(1);

	info("fib1:%d", fib1(1));


}

void test3()
{
	import core.stdc.stdio:printfc = printf;

	extern(C) int function(int ) fib1;

	string hel = "hello123";
	
	TCCState* ptccstate = null;
	scope(exit){
		if(ptccstate !is null) tcc_delete(ptccstate);
	}
	ptccstate = tcc_new();
	if(ptccstate is null)
	{
		info("not create tcc state");
	}
	//ptccstate.tcc_set_error_func(null, &disErr);
	//ptccstate.tcc_set_error_func(null, function(void*,void*){});
	ptccstate.tcc_set_options(` -v`.toStringz());
	ptccstate.tcc_set_options(` -vv`.toStringz());
	ptccstate.tcc_set_options(` -run`.toStringz());
	ptccstate.tcc_set_options(` -nostdlib`.toStringz());
	ptccstate.tcc_set_output_type(TCC_OUTPUT_MEMORY);

	//tcc_add_symbol(tccstate,"printf".toStringz,&ff1);
	ptccstate.tcc_add_symbol(`printf`.toStringz,&printfc);

	if(ptccstate.tcc_compile_string(helloC2) == -1)
	{
		info("compile error");
		return;
	}

	//auto v1 = ptccstate.tcc_run(0,null);
	ptccstate.tcc_add_symbol(`hello`.toStringz,(hel.ptr));

	//ptccstate.tcc_run(0,null);

	if(ptccstate.tcc_relocate(TCC_RELOCATE_AUTO) < 0)
	{
		info("relocate error");
		return;
	}
	fib1 = cast(typeof(fib1))ptccstate.tcc_get_symbol("fib");

	auto v2 = fib1(1);

	info("fib(10) = ",v2);
	//info("v1 = ",v1);
	


}

void test2()
{
    import std.stdio;
    

    /// Create a new TranslationUnit.
    auto tccstate = tcc_new();
    /// Delete the TranslationUnit upon leaving main.
    scope(exit)
        tcc_delete(tccstate);

	//tccstate.tcc_set_output_type(TCC_OUTPUT_MEMORY);
	//tcc_set_options(tccstate,"-nostdlib".toStringz);
	//-nostdinc
	//tcc_set_options(tccstate,"-nostdinc".toStringz);

	tcc_set_options(tccstate,`-vv`.toStringz);
	tcc_set_options(tccstate,`-v`.toStringz);
	tcc_set_options(tccstate,`-m64`.toStringz);

	tccstate.tcc_add_library_path(`.\lib`.toStringz);
	//tccstate.tcc_add_library("libtcc1-64.a".toStringz);
	

    /// Assert if Error.
    assert( 0 <= tcc_compile_string(tccstate, helloC.toStringz)  );

    writefln( "Running:\n%s", helloC);
    
    /// Now run the new file passing along the args.
    /// tcc_run( tccstate, int argc, char** argv);
    auto ret = tcc_run(tccstate, 0, null);

	info("ret :",ret);

    //assert( 9 == ret );
}



/*
void* Tcc(in string str)
{
	auto tccstate = tcc_new();
	scope(exit)
		tcc_delete(tccstate);
	tcc_set_options(tccstate,"-nostdlib".toStringz);
	tcc_set_options(tccstate,"-nostdinc".toStringz);

	foreach(ref k,ref v;gSymbol)
	{
		tcc_add_symbol(tccstate,k.toStringz,v);
	}

	tcc_compile_string(tccstate,str.toStringz);

	int size=tcc_relocate(tccstate, null);
	auto exa = GC.calloc(size);
	tcc_relocate(tccstate, exa);

	return tcc_get_symbol(tccstate, "apo1");

}
*/

extern(C)
void* malloc1( size_t sz) 
{
	info("malloc1");
	import core.memory;
	//GC.malloc()
	auto yyu = GC.malloc( sz );
	if(yyu)
	{
		auto aa = sz;
	}
	return yyu;
}
extern(C)
void _start()
{
	info("start");

}

extern(C)
void ff1(char* v)
{
	info("ff1");

}


void loop1()
{
	//import core.stdc.stdio;
	import core.memory;
	import std.string: toStringz;
	//import core.stdc.string;
	auto tccstate = tcc_new();
	scope(exit)        tcc_delete(tccstate);
	tcc_set_options(tccstate,"-nostdlib".toStringz);
	//-nostdinc
	tcc_set_options(tccstate,"-nostdinc".toStringz);

	//tcc_add_library_path(tccstate,`lib`.toStringz);
	tcc_add_symbol(tccstate,"printf".toStringz,&ff1);
	tcc_add_symbol(tccstate,"malloc".toStringz,&malloc1);
	tcc_add_symbol(tccstate,"_start".toStringz,&_start);

	tcc_compile_string(tccstate, `
			void apo(){ printf("Hello World!abc\n"); }
			  void apo1(){ 
				  void* psa = malloc(102400); 
				  printf("Hell77777o World!abc\n"); 
				  }`.toStringz);
	int size=tcc_relocate(tccstate, null);

	auto exa = GC.calloc(size);

	auto r1 = tcc_relocate(tccstate, exa);

	auto exa1 = cast(void function())tcc_get_symbol(tccstate, "apo1");

	exa1();


	//GC.free(exa);


//	writeln("Hello D-World!");

}
